const assert = require("assert");
const { createRandomIntWithSeed } = require("../helpers");

Feature("Richtext perfomance");

// Generate text and results generator
const SYMBOLS = "abcdefghijklmnopqrstuvwxyz";
const NEWLINE = "/n";
const SPACE = " ";
const MIN_WORD_SIZE = 2;
const MAX_WORD_SIZE = 23;

function generateAnnotationParams(sybolsNum, regionsNum, seed = 42) {
  const genWord = (len) => {
    const start = length % SYMBOLS.length;
    const end = start + len;
    const s = SYMBOLS.repeat(Math.ceil(end / SYMBOLS.length));

    return s.substring(start, end);
  };
  const words = [];
  const randomInt = createRandomIntWithSeed(seed);
  let length = 0;
  let paragraphWords = randomInt(0, 150);

  let currentWordLength;

  while ((currentWordLength = Math.min(randomInt(MIN_WORD_SIZE, MAX_WORD_SIZE), sybolsNum - length)) > 0) {
    words.push(genWord(currentWordLength));
    length += currentWordLength;
    if (--paragraphWords < 1) {
      words.push(NEWLINE);
      paragraphWords = randomInt(0, 50);
    } else {
      words.push(SPACE);
    }
  }
  const text = words.join("");

  return {
    config: `<View>
    <Labels name="label" toName="text">
        <Label value="Label" background="green"/>
    </Labels>
    <Text name="text" value="$text" />
</View>`,
    data: {
      text,
    },
    annotations: [
      {
        id: "test",
        result: Array.from({ length: regionsNum }, (v, idx) => {
          const startOffset = randomInt(0, text.length - 2);
          const endOffset = startOffset + Math.min(randomInt(1, 50), text.length - startOffset);

          return {
            id: `1_${idx}`,
            from_name: "label",
            to_name: "text",
            type: "labels",
            value: { start: startOffset, end: endOffset, labels: ["Label"] },
          };
        }),
      },
    ],
  };
}

// Feel free to make this test skipped in case of needness
Scenario("Rich text initialization in hightload conditions", async ({ I, LabelStudio, AtOutliner }) => {
  const SYMBOLS_NUM = 100000;
  const REGIONS_NUM = 2000;

  // Generate text and results to reach 100K symbols and 2К labels
  const params = generateAnnotationParams(SYMBOLS_NUM, REGIONS_NUM);

  I.amOnPage("/");
  I.executeScript(async () => {
    new Promise((resolve) => {
      const watchLabelStudioReady = () => {
        const isReady = window.document.querySelector(".lsf-richtext");

        if (isReady) {
          window._startTime = Date.now();
          resolve(true);
        } else {
          setTimeout(watchLabelStudioReady, 100);
        }
      };

      watchLabelStudioReady();
    }).then(() => {
      new Promise((resolve) => {
        const watchObjectsReady = () => {
          const isReady = window.Htx && window.Htx.annotationStore.selected.objects.every((object) => object.isReady);

          if (isReady) {
            window._loadedTime = Date.now();
            resolve(true);
          } else {
            setTimeout(watchObjectsReady, 100);
          }
        };

        watchObjectsReady();
      });
    });
  });
  LabelStudio.init(params);
  LabelStudio.waitForObjectsReady();
  const initDuration = await I.executeScript(() => {
    return window._loadedTime - window._startTime;
  });

  I.say(`An annotation initialization has taken ${initDuration / 1000}s`);

  // Actually it could take 3.5-6s but "it depends..."
  assert(
    initDuration < 10000,
    `Annotation with 2K regions should be ready to interaction in less than 10s. Right now it's ${
      initDuration / 1000
    }s`,
  );
});
